package examples.jsf.context;

import examples.jsf.Application;
import examples.jsf.component.UIViewRoot;

import javax.el.ELContext;

/**
 * @author Bill
 * @version 2013-05-29
 */
public abstract class FacesContext {

    private FacesContext defaultFacesContext;

    private static volatile ThreadLocal<FacesContext> instance = new ThreadLocal<FacesContext>();

    public static FacesContext getCurrentInstance() {
        return instance.get();
    }

    protected static void setInstance(FacesContext context) {
        if (context == null) {
            instance.remove();
        } else {
            instance.set(context);
        }
    }

    public abstract PartialViewContext getPartialViewContext();

    public abstract Application getApplication();

    public abstract ELContext getELContext();

    public abstract UIViewRoot getViewRoot();

    /**
     * <p>Return <code>true</code> if the <code>renderResponse()</code>
     * method has been called for the current request.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public abstract boolean getRenderResponse();

    /**
     * <p>Signal the JavaServer faces implementation that, as soon as the
     * current phase of the request processing lifecycle has been completed,
     * control should be passed to the <em>Render Response</em> phase,
     * bypassing any phases that have not been executed yet.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public abstract void renderResponse();

    /**
     * <p>Return <code>true</code> if the <code>responseComplete()</code>
     * method has been called for the current request.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public abstract boolean getResponseComplete();


    /**
     * <p>Signal the JavaServer Faces implementation that the HTTP response
     * for this request has already been generated (such as an HTTP redirect),
     * and that the request processing lifecycle should be terminated as soon
     * as the current phase is completed.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public abstract void responseComplete();


    /**
     * <p class="changed_added_2_0">Sets a flag which indicates that a conversion or
     * validation error occurred while processing the inputs. Inputs consist of
     * either page parameters or form bindings. This flag can be read using
     * {@link #isValidationFailed}.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public void validationFailed() {

        if (defaultFacesContext != null) {
            defaultFacesContext.validationFailed();
        } else {
            throw new UnsupportedOperationException();
        }

    }

    /**
     * <p class="changed_added_2_0">Return <code>true</code> if the <code>validationFailed()</code>
     * method has been called for the current request.</p>
     *
     * @throws IllegalStateException if this method is called after
     *  this instance has been released
     */
    public boolean isValidationFailed() {
        if (defaultFacesContext != null) {
            return defaultFacesContext.isValidationFailed();
        }

        throw new UnsupportedOperationException();

    }


    public abstract void release();

}
